﻿/*
 * Created by SharpDevelop.
 * User: phtrung
 * Date: 8/6/2008
 * Time: 6:16 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Collections;
using System.Security.Cryptography;
using System.Text;
using Microsoft.VisualBasic.CompilerServices;
using Microsoft.VisualBasic;
using popLib.ModelSystem;
using System.Reflection;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Globalization;


namespace popLib
{
	/// <summary>
	/// Description of stringCls.
	/// </summary>
	public static class StringLib
	{
		//get arraylist of all string, that apdapt with this condition (from A to B)
		public static ArrayList getListGroupString(string src, string from, string to){
			int startIndex = 0;
			ArrayList result = new ArrayList();
			
			while( startIndex >=0 ){
				string imageStr = subString( src, from, to, startIndex);
				
				if(imageStr.Trim().Length == 0) break;
				
				startIndex = src.IndexOf( imageStr, startIndex ) + 1;
				
				result.Add(imageStr);
			}
			return result;
		}
		
		
		
		//get arraylist of all string, that apdapt with this condition (from A to B, without A,B)
		public static ArrayList getListGroupStringInside(string src, string from, string to){
			int startIndex = 0;
			ArrayList result = new ArrayList();
			
			while( startIndex >=0 ){
				string imageStr = subStringBetween( src, from, to, startIndex);
				
				if(imageStr.Trim().Length == 0) break;
				
				startIndex = src.IndexOf( imageStr, startIndex ) + 1;
				
				result.Add(imageStr);
			}
			return result;
		}
		
		//get string from string A, to string B but dont have A and B
		//12345678 --> get from 23 to 78 --> 456
		public static string subStringBetween(string src, string from, string to, int fromIndex){
			return subString(src,from,to,fromIndex).Replace(from,"").Replace(to,"");
		}
		//get string from string A, to string B
		//12345678 --> get from 23 to 78 --> 2345678
		public static string subString(string src, string from, string to, int fromIndex){
			string result = "";
			
			if(src.IndexOf(from,fromIndex) >= 0 ){
				int startIndex = src.IndexOf(from,fromIndex);
				int endIndex   = src.IndexOf(to, startIndex + from.Length);
				int length	   = endIndex - startIndex + to.Length;
				if(startIndex >= 0 && length > 0)
					result = src.Substring( startIndex, length);
			}
			return result;
		}
		
		//matchAny: str1;str2;str3
		public static int indexOfAny(string str, string matchAny){
			for( int i = 0; i < matchAny.Length; i++ ){
				string oneChar = matchAny.Substring(i,1);
				if( str.IndexOf(oneChar) >= 0 )
					return str.IndexOf(oneChar);
			}
			return -1;
		}
		
		//matchAny: str1;str2;str3
		public static int indexOfAny(string name, string[] matchAny){
			foreach(string item in matchAny)
				if(name.IndexOf(item)>=0) return name.IndexOf(item);
			return -1;
		}
		
		public static string decodeSpecialChar(string content){
			return content.Replace("\\r","\r").Replace("\\n","\n").Replace("\\t","\t");
		}
		
		public static string encodeSpecialChar(string content){
			return content.Replace("\r","\\r").Replace("\n","\\n").Replace("\t","\\t");
		}
		
		
		public static string UpperFirstLetter(this string str){
			string firstLetter = str.Substring(0,1);
			return firstLetter.ToUpper() + str.Substring(1);
		}
		
		public static string LowerFirstLetter(this string str){
			string firstLetter = str.Substring(0,1);
			return firstLetter.ToLower() + str.Substring(1);
		}
		
		/// <summary>
		/// Split input string to string array by split input string depend on one of the list
		/// of passed string[] separaters
		/// </summary>
		/// <param name="str"></param>
		/// <param name="separaters"></param>
		/// <returns></returns>
		public static string[] SplitByAny( this string str, string[] separaters ){
			string[] items = str.Replace( separaters[0], (char)(127)+"" ).Split( (char)(127) );
			foreach( string separater in separaters )
				if( str.IndexOf(separater) >= 0 )
				items = str.Replace( separater, (char)(127)+"" ).Split( (char)(127) );
			
			return items;
		}
		
		/// <summary>
		/// Split input string to string[] by split using each letter of the separaters
		/// Note: use for split with separator is single character only.
		/// </summary>
		/// <param name="str"></param>
		/// <param name="separaters"></param>
		/// <returns></returns>
		public static string[] SplitByAny( this string str, string separaters ){
			string[] items = str.Replace( separaters.Substring(0,1), (char)(127)+"" ).Split( (char)(127) );
			for( int i = 0; i < separaters.Length; i++ ){
				string separater = separaters.Substring(i,1);
				if( str.IndexOf(separater) >= 0 )
                    items = str.Replace(separater, (char)(127) + "").Split((char)(127));
			}
			
			return items;
		}
		
		/// <summary>
		/// Convert String to hashtable with specific rule and splitter string		
		/// </summary>
		/// <param name="options">key=value&key=value or key:value\r\nkey:value</param>
		/// <param name="optionSplitterChar">Splitter character between each option &</param>
		/// <param name="valueSpliterChar">Splitter character between key and value (for each option) =</param>
		/// <returns></returns>
        public static Hashtable parseOption(string options, char optionSplitterChar = '&', char valueSpliterChar = '=')
        {
			Hashtable result = new Hashtable();
			
			if(options != null){
                options = parseHashString(options, HashStringType.DoubleChar_SpecialChar, optionSplitterChar, valueSpliterChar);
				string[] optionArr = SplitByAny(options, optionSplitterChar.ToString() );
				string[] content;
				
				foreach( string option in optionArr ){
					if( !option.Contains(valueSpliterChar.ToString()) ) continue;
					
					content = StringLib.Replace1time( option, valueSpliterChar.ToString(), (char)(127) + "" ).Split( (char)(127) );
					
					if(content.Length == 2){
                        result.Add( parseHashString(content[0], HashStringType.SpecialChar_Char, optionSplitterChar, valueSpliterChar)
                            , parseHashString(content[1], HashStringType.SpecialChar_Char, optionSplitterChar, valueSpliterChar));
					}
				}
			}
			
			return result;
		}
		

		
		/// <summary>
		/// Convert hashtable to string specific rule and splitter string
		/// </summary>
		/// <param name="options">hashtable</param>
		/// <param name="optionSplitterChar">& or \r\n or something else</param>
		/// <param name="valueSpliterChar">= or : or anything else</param>
		/// <returns></returns>
		public static string deParseOption( Hashtable options, char optionSplitterChar = '&', char valueSpliterChar = '=' ){

			string result = "", key = "", value = "";
			foreach( string skey in options.Keys ){

                key = parseHashString(skey, HashStringType.Char_DoubleChar, optionSplitterChar, valueSpliterChar);
                value = parseHashString(options[skey].ToString(), HashStringType.Char_DoubleChar, optionSplitterChar, valueSpliterChar);

				result += string.Format( "{0}{2}{1}{3}", key, value , valueSpliterChar.ToString(), optionSplitterChar.ToString() );
			}

            if (result.EndsWith(optionSplitterChar.ToString()))
                result = result.Substring(0, result.Length - 1);
			return result;
		}


        private enum HashStringType { Char_DoubleChar, DoubleChar_SpecialChar, SpecialChar_Char }
        private static string parseHashString(string content, HashStringType parseType, char optionSplitterChar = '&', char valueSpliterChar = '=')
        {
            switch (parseType)
            {
                default:
                case HashStringType.Char_DoubleChar:
                    return content.Replace(optionSplitterChar + "", optionSplitterChar + "" + optionSplitterChar).Replace(valueSpliterChar + "", valueSpliterChar + "" + valueSpliterChar);
                case HashStringType.DoubleChar_SpecialChar:
                    return content.Replace(optionSplitterChar + "" + optionSplitterChar, (char)128 + "").Replace(valueSpliterChar + "" + valueSpliterChar, (char)129 + "");
                case HashStringType.SpecialChar_Char:
                    return content.Replace((char)128 + "", optionSplitterChar + "").Replace((char)129 + "", valueSpliterChar + "");
            }
        }

		//Return space left of a string
		public static  string spaceleft(string currentStr,int totallength)
		{
			return spaceleft( currentStr, totallength, " " );
		}
		
		//Return character left of a string
		public static  string spaceleft(string currentStr, int totalLength, string newChar)
		{
			string spacereturn = "";
			if(currentStr.Length<totalLength)
			{
				for(int i=0;i<totalLength - currentStr.Length;i++)
					spacereturn += newChar;
			}
			return spacereturn;
		}
		
		public static string spaceLeftInclude( object currentStr,int totalLength, string newChar ){
			return spaceleft( currentStr+"", totalLength, newChar ) + currentStr;
		}
		public static string spaceLeftInclude( object currentStr,int totalLength ){
			return spaceleft( currentStr+"", totalLength, " " ) + currentStr;
		}
		
		//Return only char that in filter list
		public static string filterStr(string var,string filstr)
		{
			string rs = "";
			for(int i=0;i<var.Length;i++)
				if(filstr.IndexOf(var.Substring(i,1)) >= 0)
				rs += var.Substring(i,1);
			return rs;
		}
		
		
		
		//Return string that is replace filstr 1 time;
		public static string Replace1time(string val,string oldstr,string newstr)
		{
			if(val.IndexOf(oldstr) >= 0)
			{
				string buf = val.Substring(0,val.IndexOf(oldstr));
				string buf1= val.Substring( val.IndexOf(oldstr)+oldstr.Length , val.Length - (val.IndexOf(oldstr)+oldstr.Length));
				return buf+newstr+buf1;
			}
			else return val;
		}
		
		public static string Encrypt64(string toEncode)
		{
			byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
			string returnValue     = System.Convert.ToBase64String(toEncodeAsBytes);
			return returnValue;
		}

        public static string Encrypt64(string toEncode, string char_key)
		{
			try{
				string lastEncode = "";
				int charIndex = -1;
				int keyLength = char_key.Length;
				
				//encode to 64base
				char_key = Encrypt64(char_key);
				toEncode = Encrypt64(toEncode);
				
				for(int i=0;i<toEncode.Length;i++){
					lastEncode+= toEncode.Substring(i,1);
					
					charIndex++;
					if(charIndex >= char_key.Length) charIndex = 0;
					lastEncode+= char_key.Substring(charIndex,1);
				}
				lastEncode = keyLength+"[[=]]"+lastEncode;
				return Encrypt64(lastEncode);
			}catch(Exception ex){ex.ToString();}
			return "#Error";
		}

        public static string Decrypt64(string encodedData)
		{
			byte[] encodedDataAsBytes = System.Convert.FromBase64String(encodedData);
			string returnValue = System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes);
			return returnValue;
		}
        public static string Decrypt64(string encodedData, string char_key)
		{
			try{
                string decoded = Decrypt64(encodedData);
				if( decoded.IndexOf("[[=]]") == -1 ) return "???#";
				int keyLength = NumberLib.getInt( SplitByAny( decoded, new string[]{"[[=]]"} )[0] );
				decoded = SplitByAny( decoded, new string[]{"[[=]]"} )[1];
				if( char_key.Length != keyLength ) return "???L";

                char_key = Encrypt64(char_key);
				string result = "";
				string compareKey = "";
				for( int i=0;i<decoded.Length;i+=2){
					result 		+= decoded.Substring(i,1);
					compareKey 	+= decoded.Substring(i+1,1);
				}
				
				string buildKey = "";
				int charIndex = -1;
				for(int i=0;i<compareKey.Length;i++){
					charIndex++;
					if(charIndex >= char_key.Length) charIndex = 0;
					buildKey+= char_key.Substring(charIndex,1);
				}
				
				if( compareKey == buildKey )
                    return Decrypt64(result);
				else return "???";
			}catch(Exception ex){ex.ToString();}
			return "#Error";
		}

        public static bool isValid(this string str)
        {
            return isValid((object)str);
        }

		public static bool isValid(object str){
			if( str != null && str.ToString().Trim().Length > 0 ) return true;
			return false;
		}
		
		
		/// <summary>
		/// Encript string with key, include md5 (optional)
		/// Support decrypt		
		/// </summary>
		/// <param name="toEncrypt">String to encript</param>
		/// <param name="key">Key to encript your string, also known as password</param>
		/// <param name="useHashing">true: to use md5 to encode</param>
		/// <returns>Encoded string</returns>
		public static string Encrypt64Byte(string toEncrypt, string key, bool useHashing)
		{
			byte[] keyArray;
			byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

			if (useHashing)
			{
				MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
				keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
			}
			else
				keyArray = UTF8Encoding.UTF8.GetBytes(key);

			TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
			tdes.Key = keyArray;
			tdes.Mode = CipherMode.ECB;
			tdes.Padding = PaddingMode.PKCS7;

			ICryptoTransform cTransform = tdes.CreateEncryptor();
			byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

			return Convert.ToBase64String(resultArray, 0, resultArray.Length);
		}
		
		/// <summary>
		/// Decript encoded string with key, include md5 (optional)
		/// </summary>
		/// <param name="toDecrypt">String to decript</param>
		/// <param name="key">Key to decript your string, also known as password</param>
		/// <param name="useHashing">True: to use md5 to encode</param>
		/// <returns>Decoded string</returns>
        public static string Decrypt64Byte(string toDecrypt, string key, bool useHashing)
		{
			byte[] keyArray;
			byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);

			if (useHashing)
			{
				MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
				keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
			}
			else
				keyArray = UTF8Encoding.UTF8.GetBytes(key);

			TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
			tdes.Key = keyArray;
			tdes.Mode = CipherMode.ECB;
			tdes.Padding = PaddingMode.PKCS7;

			ICryptoTransform cTransform = tdes.CreateDecryptor();
			byte[] resultArray= cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

			return UTF8Encoding.UTF8.GetString(resultArray);
		}
		
		
		
		/// <summary>
		/// Encrypt password in MD5 or SHA1
		/// </summary>
		/// <param name="password">string password to encode</param>
		/// <param name="format">Format could be MD5 or SHA1</param>
		/// <returns>Ecrypted string</returns>
        public static string MD5(string password)
        {
            byte[] textBytes = System.Text.Encoding.Default.GetBytes(password);
            try
            {
                System.Security.Cryptography.MD5CryptoServiceProvider cryptHandler;
                cryptHandler = new System.Security.Cryptography.MD5CryptoServiceProvider();
                byte[] hash = cryptHandler.ComputeHash(textBytes);
                string ret = "";
                foreach (byte a in hash)
                {
                    if (a < 16)
                        ret += "0" + a.ToString("x");
                    else
                        ret += a.ToString("x");
                }
                return ret;
            }
            catch
            {
                throw;
            }
        }

        public static string[] splitByLine(this string content)
        {
            return StringLib.SplitByAny(content, new string[] { "\r\n" });
        }

        public static string[] splitByTab(this string content)
        {
            return StringLib.SplitByAny(content, new string[] { "\t" });
        }

        public static string ConvertTCVN2Unicode(this string content)
        {
            if (!content.isValid()) return "";

            string tcvnchars = "­µ¸¶·¹¨»¾¼½Æ©ÇÊÈÉË®ÌÐÎÏÑªÒÕÓÔÖ×ÝØÜÞßãáâä«åèæçé¬êíëìîïóñòô*õøö÷ùúýûüþ¡¢§£¤¥¦";
            char[] unichars = { 'ư', 'à', 'á', 'ả', 'ã', 'ạ', 'ă', 'ằ', 'ắ', 'ẳ', 'ẵ', 'ặ', 'â', 'ầ', 'ấ', 'ẩ', 'ẫ', 'ậ', 'đ', 'è', 'é', 'ẻ', 'ẽ', 'ẹ', 'ê', 'ề', 'ế', 'ể', 'ễ', 'ệ', 'ì', 'í', 'ỉ', 'ĩ', 'ị', 'ò', 'ó', 'ỏ', 'õ', 'ọ', 'ô', 'ồ', 'ố', 'ổ', 'ỗ', 'ộ', 'ơ', 'ờ', 'ớ', 'ở', 'ỡ', 'ợ', 'ù', 'ú', 'ủ', 'ũ', 'ụ', 'ư', 'ừ', 'ứ', 'ử', 'ữ', 'ự', 'ỳ', 'ý', 'ỷ', 'ỹ', 'ỵ', 'Ă', 'Â', 'Đ', 'Ê', 'Ô', 'Ơ', 'Ư' };
            string result = "";
            for (int i = 0; i < content.Length; i++)
            {
                if (tcvnchars.Contains(content[i] + ""))
                {
                    result += unichars[tcvnchars.IndexOf(content[i] + "")];
                }
                else result += content[i];
            }
            return result;
        }

        public static string ConvertVNI2Unicode(this string content)
        {
            if (!content.isValid()) return "";

            int[] maAcii = new int[134] { 7845, 7847, 7849, 7851, 7853, 226, 7843, 227, 7841, 7855, 7857, 7859, 7861, 7863, 259, 250, 249, 7911, 361, 7909, 7913, 7915, 7917, 7919, 7921, 432, 7871, 7873, 7875, 7877, 7879, 234, 233, 232, 7867, 7869, 7865, 7889, 7891, 7893, 7895, 7897, 7887, 245, 7885, 7899, 7901, 7903, 7905, 7907, 417, 237, 236, 7881, 297, 7883, 253, 7923, 7927, 7929, 7925, 273, 7844, 7846, 7848, 7850, 7852, 194, 7842, 195, 7840, 7854, 7856, 7858, 7860, 7862, 258, 218, 217, 7910, 360, 7908, 7912, 7914, 7916, 7918, 7920, 431, 7870, 7872, 7874, 7876, 7878, 202, 201, 200, 7866, 7868, 7864, 7888, 7890, 7892, 7894, 7896, 7886, 213, 7884, 7898, 7900, 7902, 7904, 7906, 416, 205, 204, 7880, 296, 7882, 221, 7922, 7926, 7928, 7924, 272, 225, 224, 244, 243, 242, 193, 192, 212, 211, 210 };

            string[] Vni = new string[134]{"aá", "aà", "aå", "aã", "aä", "aâ", "aû", "aõ", "aï", "aé", "aè",

                            "aú", "aü", "aë", "aê", "uù", "uø", "uû", "uõ", "uï", "öù", "öø", "öû", "öõ",

                            "öï", "ö", "eá", "eà", "eå", "eã", "eä", "eâ", "eù", "eø", "eû", "eõ", "eï",

                            "oá", "oà", "oå", "oã", "oä", "oû", "oõ", "oï", "ôù", "ôø",

                            "ôû", "ôõ", "ôï", "ô", "í", "ì", "æ", "ó", "ò", "yù", "yø", "yû", "yõ", "î",

                            "ñ", "AÁ", "AÀ", "AÅ", "AÃ", "AÄ", "AÂ", "AÛ", "AÕ",

                            "AÏ", "AÉ", "AÈ", "AÚ", "AÜ", "AË", "AÊ", "UÙ", "UØ", "UÛ", "UÕ",

                            "UÏ", "ÖÙ", "ÖØ", "ÖÛ", "ÖÕ", "ÖÏ", "Ö", "EÁ", "EÀ", "EÅ",

                            "EÃ", "EÄ", "EÂ", "EÙ", "EØ", "EÛ", "EÕ", "EÏ", "OÁ", "OÀ", "OÅ",

                            "OÃ", "OÄ", "OÛ", "OÕ", "OÏ", "ÔÙ", "ÔØ", "ÔÛ",

                            "ÔÕ", "ÔÏ", "Ô", "Í", "Ì", "Æ", "Ó", "Ò", "YÙ", "YØ", "YÛ", "YÕ",

                            "Î", "Ñ", "aù", "aø", "oâ", "où", "oø", "AÙ", "AØ", "OÂ", "OÙ", "OØ"};



            string result = content;

            for (int i = 0; i < 134; i++)
            {

                result = result.Replace(Vni[i], Convert.ToChar(maAcii[i]).ToString());

            }

            return result;
        }

        public static string ConvertUnicodeToASCII(this string content)
        {
            if (!content.isValid()) return "";

            string src = "áàảãạâấầẩẫậăắằẳẵặđéèẻẽẹêếềểễệíìỉĩịóòỏõọôốồổỗộơớờởỡợúùủũụưứừửữựýỳỷỹỵÁÀẢÃẠÂẤẦẨẪẬĂẮẰẲẴẶĐÉÈẺẼẸÊẾỀỂỄỆÍÌỈĨỊÓÒỎÕỌÔỐỒỔỖỘƠỚỜỞỠỢÚÙỦŨỤƯỨỪỬỮỰÝỲỶỸỴ";
            string src1 = "aaaaaaaaaaaaaaaaadeeeeeeeeeeeiiiiiooooooooooooooooouuuuuuuuuuuyyyyyAAAAAAAAAAAAAAAAADEEEEEEEEEEEIIIIIOOOOOOOOOOOOOOOOOUUUUUUUUUUUYYYYY";
            string str = "";
            string str1 = "";
            for (int i = 0; i < src.Length; i++)
            {
                str = src.Substring(i, 1);
                str1 = src1.Substring(i, 1);
                content = content.Replace(str, str1);
            }

            return content;
        }

        public static string ConvertEscASCIIToUnicode(this string content)
        {
            return Regex.Replace(
            content,
            @"\\u(?<Value>[a-zA-Z0-9]{4})",
            m =>
            {
                return ((char)int.Parse(m.Groups["Value"].Value, NumberStyles.HexNumber)).ToString();
            });
        }

        public static string ConvertUnicodeToEscASCII(this string content)
        {
            StringBuilder sb = new StringBuilder();
            foreach (char c in content)
            {
                if (c > 127)
                {
                    // This character is too big for ASCII
                    string encodedValue = "\\u" + ((int)c).ToString("x4");
                    sb.Append(encodedValue);
                }
                else
                {
                    sb.Append(c);
                }
            }
            return sb.ToString();
        }

        public static string GetString(object content, string defaultString = "")
        {
            if (content == null) return "";
            return content.ToString();
        }

        public static String GetString(this object obj)
        {
            if (obj == null)
            {
                return "";
            }

            return obj.ToString();
        }

        public static bool GetBoolean(this object obj)
        {
            if (obj == null)
            {
                return false;
            }

            if (StringLib.indexOfAny(obj.GetType().Name.ToUpper(), new string[] { "INT", "DOUBLE", "LONG" }) >= 0)
            {
                return NumberLib.getDouble(obj) > 0;
            }
            try
            {
                return Convert.ToBoolean(obj);
            }
            catch { return false; }
        }
        
        public static string DecryptSC(string A_0)
        {
            if ((StringType.StrCmp(A_0, null, false) == 0) || (StringType.StrCmp(A_0, string.Empty, false) == 0))
            {
                return A_0;
            }
            string str2 = string.Empty;
            int num2 = A_0.Length ^ 0x80;
            if (num2 < 0x20)
            {
                num2 += 0x20;
            }
            else if (num2 > 0xfe)
            {
                num2 = num2 % 0xfe;
                if (num2 < 0x20)
                {
                    num2 += 0x20;
                }
            }
            int num5 = A_0.Length - 1;
            for (int i = 0; i <= num5; i++)
            {
                if (Strings.AscW(A_0.Substring(i, 1)) == num2)
                {
                    str2 = str2 + A_0.Substring(i, 1);
                }
                else if (StringType.StrCmp(StringType.FromChar(Strings.ChrW(Strings.AscW(A_0.Substring(i, 1)) ^ num2)), "&", false) == 0)
                {
                    str2 = str2 + A_0.Substring(i, 1);
                }
                else if (((Strings.AscW(A_0.Substring(i, 1)) ^ num2) >= 0x20) & ((Strings.AscW(A_0.Substring(i, 1)) ^ num2) <= 0xfe))
                {
                    str2 = str2 + StringType.FromChar(Strings.ChrW(Strings.AscW(A_0.Substring(i, 1)) ^ num2));
                }
                else
                {
                    str2 = str2 + A_0.Substring(i, 1);
                }
            }
            return str2;
        }

        public static string EncryptSC(string A_0)
        {
            if ((StringType.StrCmp(A_0, null, false) == 0) || (StringType.StrCmp(A_0, string.Empty, false) == 0))
            {
                return A_0;
            }
            string str2 = string.Empty;
            int num2 = A_0.Length ^ 0x80;
            if (num2 < 0x20)
            {
                num2 += 0x20;
            }
            else if (num2 > 0xfe)
            {
                num2 = num2 % 0xfe;
                if (num2 < 0x20)
                {
                    num2 += 0x20;
                }
            }
            int num6 = A_0.Length - 1;
            for (int i = 0; i <= num6; i++)
            {
                if (Strings.AscW(A_0.Substring(i, 1)) == num2)
                {
                    str2 = str2 + A_0.Substring(i, 1);
                }
                else if (StringType.StrCmp(StringType.FromChar(Strings.ChrW(Strings.AscW(A_0.Substring(i, 1)) ^ num2)), "&", false) == 0)
                {
                    str2 = str2 + A_0.Substring(i, 1);
                }
                else if (((Strings.AscW(A_0.Substring(i, 1)) ^ num2) >= 0x20) & ((Strings.AscW(A_0.Substring(i, 1)) ^ num2) <= 0xfe))
                {
                    str2 = str2 + StringType.FromChar(Strings.ChrW(Strings.AscW(A_0.Substring(i, 1)) ^ num2));
                }
                else
                {
                    str2 = str2 + A_0.Substring(i, 1);
                }
            }
            return str2;
        }

        public static string ConvertObjectToString(object obj)
        {
            Hashtable data = new Hashtable();

            PropertyInfo[] properties = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
            foreach (var prop in properties)
            {
                if (!"INT INT16 INT32 INT64 LONG BOOL BOOLEAN DOUBLE STRING DATETIME".Contains(Global.GetPropertyTypeName(prop).ToUpper())) continue;
                data.Add(prop.Name, prop.GetValue(obj, null) == null ? "[NULL]" : prop.GetValue(obj, null));
            }

            return StringLib.deParseOption(data);
        }

        public static ReturnSet ConvertStringToObject(object obj, string dataStr, bool verifyData = false)
        {
            Hashtable data = StringLib.parseOption(dataStr);

            PropertyInfo[] properties = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
            foreach (var prop in properties)
            {
                if (!"INT INT16 INT32 INT64 LONG BOOL BOOLEAN DOUBLE STRING DATETIME".Contains(Global.GetPropertyTypeName(prop).ToUpper())) continue;
                if (!data.ContainsKey(prop.Name)) continue;
                if (data[prop.Name].ToString() == "[NULL]") continue;

                switch (Global.GetPropertyTypeName(prop).ToUpper())
                {
                    case "BOOL":
                    case "BOOLEAN":
                        prop.SetValue(obj, data[prop.Name].ToString() == "True" ? true : false, null);
                        break;
                    case "DOUBLE":
                        prop.SetValue(obj, NumberLib.getDouble(data[prop.Name]), null);
                        break;
                    case "DATETIME":
                        prop.SetValue(obj, DateTime.Parse(data[prop.Name].ToString()), null);
                        break;
                    case "STRING":
                        prop.SetValue(obj, data[prop.Name], null);
                        break;
                    case "INT64":
                    case "LONG":
                        prop.SetValue(obj, NumberLib.getInt64(data[prop.Name]), null);
                        break;
                    default:
                        prop.SetValue(obj, NumberLib.getInt(data[prop.Name]), null);
                        break;
                }
            }

            if (verifyData)
            {
                if (ConvertObjectToString(obj) != dataStr)
                    return new ReturnSet(false, obj);
            }


            return new ReturnSet(true, obj);
        }

        public static void SaveObjectListToFile(List<object> datasource, string filename)
        {
            int total = datasource.Count;

            string content = "";
            foreach (var item in datasource)
            {
                content += ConvertObjectToString(item) + "\r\n";
            }
            FileLib.writeFile(filename, content);
        }

        public static ReturnSet LoadObjectListFromFile(string file, Type type, bool verifyData = false)
        {
            List<object> result = new List<object>();
            if (!File.Exists(file)) return new ReturnSet(false, null, "File is not existed!!");

            string content = FileLib.readFile(file);
            foreach (string line in content.splitByLine())
            {
                if (!line.isValid()) continue;
                object obj = Activator.CreateInstance(type);
                ReturnSet rs = ConvertStringToObject(obj, line, verifyData);
                if (rs.Success)
                    result.Add(obj);
                else return new ReturnSet(false, null, "Error line:" + line);
            }

            return new ReturnSet(true, result);
        }

    }
}
